/*
 *File: BlockLinkedList.cpp
 *Authors: Diane, Dan, and Tim
 *Created Oct 2012
 */

#include "BlockLinkedList.h"
#include "Disk.h"
#include "FSBlock.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <unistd.h> // Mac OS X
// Will probably need to clean up/add/subtract #include


BlockLinkedList::BlockLinkedList() {
	m_disk = new disk("disk", DEFAULT_NUMBER_OF_BLOCKS, disk::DEFAULT_BLOCK_SIZE);
	m_blockSize = disk::DEFAULT_BLOCK_SIZE;
	m_numberOfBlocks = 0;
	m_endBlockNumber = 0;
	m_startBlockNumber = 0;
	m_seek = NULL;
}

BlockLinkedList::BlockLinkedList(Disk * disk, unsigned int blockSize){
	m_disk = disk;
	m_blockSize = blockSize;
	m_numberOfBlocks = 0;
	m_endBlockNumber = NULL;
	m_startBlockNumber = NULL;
	m_seek = NULL;
}

BlockLinkedList::BlockLinkedList(BlockLinkedList * b){
	m_disk = b->GetDisk();
	m_blockSize = b->GetBlockSize();
	m_numberOfBlocks = 0;
	m_endBlockNumber = 0;
	m_startBlockNumber = 0;
	m_seek = NULL;
}

BlockLinkedList::Disk* GetDisk(){
	return m_disk;
}

bool BlockLinkedList::Initialize(int blockNumber){
	/*

	*/
	m_numberOfBlocks = 1;
	m_startBlockNumber = blockNumber;
	m_endBlockNumber = blockNumber;
	m_currentBlockNumber = blockNumber;
	FSBlock firstBlock(blockNumber, Disk::DEFAULT_BLOCK_SIZE);
	firstBlock.clearBuffer();
	firstBlock.setNext(0);
	return firstBlock.write(m_disk);
}

int BlockLinkedList::GetBlockSize(){
	return (m_blockSize - 4);

}

int BlockLinkedList::GetNumberOfBlocks(){
	return m_numberOfBlocks;
}

BlockLinkedList::FSBlock* UnlinkBlock(){
	if(0 == m_numberOfBlocks)
		return NULL;

	FSBlock* blockPointer;
	try{
		blockPointer = new FSBlock(m_startBlockNumber, m_disk);
		if(m_currentBlockNumber == m_startBlockNumber)
			currentBlockNumber = blockPointer->getNext();
			m_startBlockNumber = blockPointer->getNext();
	}
	catch(CannotReadException e){
		return NULL;
	}
	m_numberOfBlocks--;
	return blockPointer
}

bool BlockLinkedList::AddBlock(FSBlock* newBlock) throw(CannotReadException){
	try {
		FSBlock endBlock(m_endBlockNumbert, m_disk);
        	m_endBlockNumber = newBlock->getBlockNumber();
        	endBlock.setNext(m_endBlockNumber);
        	if(!endBlock.write(m_disk))
           	 return false;
	}
	catch(CannotReadException e){
        	throw e;
        	return false;
	}

	// Clear and write the new block    
	newBlock->clearBuffer();
	newBlock->setNext(0);
	if(newBlock->write(m_disk)){
  	        m_numberOfBlocks++;
	        return true;
	}
	else
        	return false;

}

int BlockLinkedList::GetStartBlockNumber(){
	return m_startBlockNumber;
}

int BlockLinkedList::GetEndBlockNumber(){
	return m_endBlockNumber;
}

void BlockLinkedList::Rewind(){
	m_currentBlockNumber = m_startBlockNumber;
}

FSBlock* BlockLinkedList::GetCurrentBlock(){
	if(m_currentBlockNumber == 0){
		return NULL;
	}
	currentBlockPointer = new FSBlock(m_currentBlockNumber, m_disk);
	return currentBlockPointer;

void BlockLinkedList::GetNextBlock(){
	if(m_currentBlockNumber == 0){
		FSBlock* currentPointer = getCurrentBlock();
		if(currentPointer != 0){
			m_currentBlockNumber = currentPointer->getNext();
			delete cureentPointer;
			return true;
		}
	} 
	else return false;
}

void BlockLinkedList::Output(){
	m_currentBlockNumber = m_startBlockNumber;
	FSBlock* currentBlockPointer = this->getCurrentBlock();

	cout << "start of list\n";
	while(currentBlockPointer != 0){
		cout << currentBlockPointer->GetBlockNumber() << ", ";
		this->getNextBlock();
		delete currentBlockPointer;
		currentBlockPointer = this->getCurrentBlock();
	}
	cout << "\nEnd of list\n";
		
}

bool BlockLinkedList::Replace(FSBlock *blk){
	//FSBlock* b = GetCurrentBlock();
	//b->SetBuffer(blk->GetBuffer());
	return false;
}

int BlockLinkedList::CountBlocks(){
	for(m_startBlockNumber != NULL){
		
	}
}

